package naga.x.platform2.channel.iapppay;

import java.util.Map;

import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import naga.x.platform2.app.Channel;
import naga.x.platform2.app.model.GameServer;
import naga.x.platform2.app.model.Recharge;
import naga.x.platform2.app.model.RechargeTemplate;
import naga.x.platform2.app.support.GameServerSupport;
import naga.x.platform2.channel.iapppay.support.BaseIAppPayConfig;
import naga.x.platform2.channel.iapppay.support.IAppPayApi;
import naga.x.platform2.channel.iapppay.support.PaySupport;
import naga.x.platform2.channel.iapppay.support.RSA;
import naga.x.platform2.support.RequestPath;
import naga.x.platform2.utils.CommonUtils;
import naga.x.platform2.utils.HttpUtils;
import naga.x.platform2.utils.IOUtils;
import naga.x.platform2.utils.NumberUtils;
import naga.x.platform2.utils.StringUtils;

/**
 * 爱贝支付<br/>
 * IAPP_PAY/TELECOM/ARKFEL共享<br/>
 * {@link Channel#IAPP_PAY}
 * {@link Channel#TELECOM}
 * {@link Channel#ARKFEL}
 * @author yang.li
 *
 */
@Controller
public class IAppPayController {

	@Autowired
	private IAppPayApi api;
	@Autowired
	private PaySupport paySupport;
	@Autowired
	private GameServerSupport gameServers;
	
//	private static Channel channel = Channel.IAPP_PAY;
	private static final Logger LOG = IAppPayApi.LOG;
	
	@RequestMapping(path = RequestPath.IAPP_USER2, produces = "application/json; charset=UTF-8")
	@ResponseBody
	public Object getUser(@PathVariable String channel, String token) {
		BaseIAppPayConfig config = api.getConfig(channel);
		if (config == null) {
			return IAppPayApi.makeError("-1", "请求超时");
		}
		String url = config.getLoginCheckUrl();
		JSONObject data = new JSONObject(true);
		data.put("appid", config.getAppId());
		data.put("logintoken", token);
		byte[] reqParams = api.makeRequestParameters(config, data);
		String resText = HttpUtils.post(url, reqParams);
		
		Map<String, String> resMap = IAppPayApi.parseUrlParameters(resText);
		String transdata = resMap.get(IAppPayApi.PARAMETER_KEY_DATA);
		JSONObject user = JSON.parseObject(transdata);
		if (user.getString("userid") != null && user.getString("loginname") != null) { // success
			user.put("code", "0");
			user.put("username", user.remove("loginname"));
		}
//		String sign = resMap.get(IAppPayApi.PARAMETER_KEY_SIGN);
//		if (StringUtils.isEmpty(sign) || !RSA.verify(transdata, sign, config.getPublicKey())) {
//			return IAppPayApi.makeError("1001", "签名验证失败~");
//		}
		return user;
	}
	
	@RequestMapping(path = RequestPath.IAP_GET_ORDER2, produces = "application/json; charset=UTF-8")
	@ResponseBody
	public Object pay(@PathVariable String channel, Integer sid, Long pid, Integer product) {
		BaseIAppPayConfig config = api.getConfig(channel);
		if (config == null) {
			return IAppPayApi.makeError("-1", "请求超时");
		}
		GameServer gs = gameServers.get(sid);
		if (gs == null) {
			LOG.info("[IAPP ORDER ERR]SERVER[{}]PLAYER[{}]PRODUCT[{}]CAUSE[{}]",
										sid, pid, product, "GSERR");
			return IAppPayApi.makeError("-1", "服务器id错误");
		}
		RechargeTemplate template = paySupport.getTemplate(product);
		if (template == null) {
			LOG.info("[IAPP ORDER ERR]SERVER[{}]PLAYER[{}]PRODUCT[{}]CAUSE[{}]",
					sid, pid, product, "PRODUCTERR");
			return IAppPayApi.makeError("-2", "充值id错误");
		}
		if (pid == null) {
			LOG.info("[IAPP ORDER ERR]SERVER[{}]PLAYER[{}]PRODUCT[{}]CAUSE[{}]",
					sid, pid, product, "PIDERR");
			return IAppPayApi.makeError("-3", "玩家id错误");
		}
		// 请求下订单
		String url = config.getPlaceOrderUrl();
		String reqParams = api.makeRequestParametersAsText(config, paySupport.makeOrderTransdata(config, gs, pid, template).toJSONString());
		String resText = HttpUtils.post(url, IOUtils.getStringBytes(reqParams, IAppPayApi.DEFAULT_CHARSET));
		// 解析订单信息
		Map<String, String> resMap = IAppPayApi.parseUrlParameters(resText);
		String transdata = resMap.get(IAppPayApi.PARAMETER_KEY_DATA);
		String sign = resMap.get(IAppPayApi.PARAMETER_KEY_SIGN);
		if (StringUtils.isEmpty(sign) || !RSA.verify(transdata, sign, config.getPublicKey())) {
			LOG.info("[IAPP ORDER ERR]SERVER[{}]PLAYER[{}]PRODUCT[{}]REQ[{}]RES[{}]CAUSE[{}]",
					sid, pid, product,
					reqParams, resText, "SIGNERR");
			return IAppPayApi.makeError("1001", "签名验证失败~");
		}
		JSONObject order = JSON.parseObject(transdata);
		String transid = order.getString("transid");
		if (StringUtils.isEmpty(transid)) {
			LOG.info("[IAPP ORDER ERR]SERVER[{}]PLAYER[{}]PRODUCT[{}]REQ[{}]RES[{}]CAUSE[{}]",
					sid, pid, product,
					reqParams, resText, "RESERR");
			return transdata;
		}
//		https://web.iapppay.com/pay/gateway?data=%7B%22tid%22%3A%2232011611081814510649%22%2C%22
//			app%22%3A%226660193785%22%2C%22url_r%22%3A%22http%3A%2F%2Fhost%3A9002%2Ftest%2Fh5.html
//			%22%2C%22url_h%22%3A%22http%3A%2F%2Fhost%3A9002%2Ftest%2Fh5.html%22%7D&sign=INRwGkQoksHDyUD1mzvrGMpDRtOkap
//			TtqpBw0W6M1QRx45tyFPiKHYgFq6YvxCxsVcdf5dkZyrdTSteimh3rwcpHZlIK1U1wLqK6BadstdpZh0LhhIkyx4OXW9ArCwFoUh9BUfOq
//			C7IFsN7bY%2BLBOIEQog2sAKysoDPu7BhAaZM%3D&sign_type=RSA
		// 下订单成功，构造客户端跳转地址
		String params = api.makeRequestParametersAsText(config, paySupport.makeClientPayTransdata(config, transid).toJSONString());
		String clientPayUrl = config.getPayUrl() + '?' + params;
		JSONObject res = new JSONObject(2, true);
		res.put("code", "0");
		res.put("url", clientPayUrl);
		LOG.info("[IAPP ORDER SUCC]SERVER[{}]PLAYER[{}]PRODUCT[{}]REQ[{}]RES[{}]URL[{}]",
				sid, pid, product,
				reqParams, resText, clientPayUrl);
		return res;
	}
	
	@RequestMapping(path = RequestPath.IAPP_PAY_CALLBACK2, produces = "application/json; charset=UTF-8")
	@ResponseBody
	public Object payCallback(@PathVariable String channel, String transdata, String sign, String signtype) {
		BaseIAppPayConfig config = api.getConfig(channel);
		if (config == null) {
			return IAppPayApi.makeError("-1", "请求超时");
		}
		String transdataDecoded = CommonUtils.decodeURL(transdata, IAppPayApi.DEFAULT_CHARSET);
		if (StringUtils.isEmpty(sign) || !RSA.verify(transdataDecoded, sign, config.getPublicKey())) {
			LOG.info("[IAPP PAY ERR]DATA[{}]SIGN[{}]SIGNTYPE[{}]CAUSE[{}]",
										transdataDecoded, sign, signtype, "SIGNERR");
			return "FAILURE";
		}
//		参数名称	参数含义	数据类型	是否可选	参数说明
//		transtype	交易类型	integer	必填	交易类型：
//		0–支付交易；
//		1–支付冲正（暂未启用）；
//		2–契约退订
//		3–自动续费
//		cporderid	商户订单号	String(64)	必填	商户订单号
//		transid	交易流水号	String(32)	必填	计费支付平台的交易流水号
//		appuserid	用户在商户应用
//		的唯一标识	String(32)	必填	用户在商户应用的唯一标识
//		appid	游戏id	String(20)	必填	平台为商户应用分配的唯一代码
//		waresid	商品编码	integer	必填	平台为应用内需计费商品分配的编码
//		feetype	计费方式	integer	必填	计费方式，具体定义见简介及注意事项
//		money	交易金额	Float(6,2)	必填	本次交易的金额（请务必严格校验商品金额与交易的金额是否一致）
//		currency	货币类型	String(32)	必填	货币类型以及单位：
//		RMB – 人民币（单位：元）
//		result	交易结果	integer	必填	交易结果：
//		0–交易成功
//		1–交易失败
//		transtime	交易完成时间	String(20)	必填	交易时间格式：
//		yyyy-mm-dd hh24:mi:ss
//		cpprivate	商户私有信息	String(64)	可选	商户私有信息
//		paytype	支付方式	integer	可选	支付方式，具体定义见简介及注意事项
//		Sign	对transdata的签名数据		必填	对transdata的签名数据
//		Signtype	签名算法类型		必填	签名算法类型，目前仅支持RSA
		JSONObject transdataObj = JSON.parseObject(transdataDecoded);
		if (transdataObj.getIntValue("result") != 0) {
			LOG.info("[IAPP PAY ERR]DATA[{}]SIGN[{}]SIGNTYPE[{}]CAUSE[{}]",
					transdataDecoded, sign, signtype, "RESULTERR");
			return "SUCCESS";
		}
		try {
			String cpprivate = transdataObj.getString("cpprivate");
			String[] strs = StringUtils.split(cpprivate, "#");
			int serverId = NumberUtils.parseInt(strs[0]);
			long playerId = NumberUtils.parseLong(strs[1]);
			int productId = NumberUtils.parseInt(strs[2]);
			RechargeTemplate product = paySupport.getTemplate(productId);
			if (product == null) {
				LOG.info("[IAPP PAY ERR]DATA[{}]SIGN[{}]SIGNTYPE[{}]CAUSE[{}]",
						transdataDecoded, sign, signtype, "PRODUCTERR");
				return "FAILURE";
			}
			float money = transdataObj.getFloatValue("money");
			if (money < product.getPrice()) {
				LOG.info("[IAPP PAY ERR]DATA[{}]SIGN[{}]SIGNTYPE[{}]CAUSE[{}]",
						transdataDecoded, sign, signtype, "MONEYERR");
				return "FAILURE";
			}
			Channel chnl = IAppPayApi.getChannel(channel);
			String orderId = chnl.prefix + transdataObj.getString("transid");
			Recharge recharge = new Recharge(orderId, playerId, serverId, (int) money, product.getStone(), productId, chnl.name);
			recharge.setAttach(transdataDecoded);
			boolean succ = paySupport.offer(recharge);
			LOG.info("[IAPP PAY SUCC]DATA[{}]SIGN[{}]SIGNTYPE[{}]RESULT[{}]",
					transdataDecoded, sign, signtype, succ ? 1 : 0);
			return "SUCCESS";
		} catch (Exception e) {
			LOG.info("[IAPP PAY ERR]DATA[{}]SIGN[{}]SIGNTYPE[{}]CAUSE[{}]",
					transdataDecoded, sign, signtype, "PARSEERR");
			LOG.error(e.getMessage(), e);
		}
		return "FAILURE";
	}
	
	@RequestMapping(path = RequestPath.IAPP_PAY_FINISH_REDIRECT2, produces = "application/json; charset=UTF-8")
	@ResponseBody
	public Object payFinish(@PathVariable String channel, String transdata, String sign, String signtype) {
		String transdataDecoded = CommonUtils.decodeURL(transdata, IAppPayApi.DEFAULT_CHARSET);
		JSONObject transdataObj = JSON.parseObject(transdataDecoded);
		if (transdataObj.getIntValue("result") != 0) {
			return "支付失败";
		}
		return "支付成功";
	}
	
	@RequestMapping(path = RequestPath.IAPP_PAY_CANCEL_REDIRECT2, produces = "application/json; charset=UTF-8")
	@ResponseBody
	public Object payCancel(@PathVariable String channel) {
		return "支付取消";
	}
	
	
}
